﻿using Edu.Abstracts;
using Edu.Contracts;
using Edu.Entitys;
using Edu.Utilities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using shortid;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.AutoMapper;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;

namespace Edu.Services
{
    public class GradStudentDto
    {

        [Required]
        public string Name { get; set; }
        [Required]
        public string PhoneNumber { get; set; }
        [Required]
        public StudentStatus Status { get; set; }
    }

    public class CreateUserDto
    {
        [Required]
        public string Name { get; set; }
        [Required]
        public string PhoneNumber { get; set; }
        [Required]
        public AreaList Area { get; set; }
    }

    public class CreateStudentDto : CreateUserDto
    {
        [Required]
        public string TeacherName { get; set; }

        [Required]
        public string TeacherPhoneNumber { get; set; }

        [Required]
        public DateTimeOffset StartStudyTime { get; set; }

        [Required]
        public JobType Job { get; set; }

        public Dictionary<AbilityType, AbilityLevelType> Levels { get; set; }
    }

    public class CreateTeacherDto : CreateUserDto
    {
        [Required]
        public JobType Job { get; set; }
    }


    [AutoMapTo(typeof(StudyTaskContent))]
    public class CreateTaskDto
    {

        [Required]
        public string Title
        {
            get;
            set;
        }

        /// <summary>
        /// 截止时间
        /// </summary>
        [Required]
        public System.DateTimeOffset DeadLine
        {
            get;
            set;
        }

        [Required]
        public string TeacherName { get; set; }
        [Required]
        public string TeacherPhoneNumber { get; set; }

        [Required]
        public string StudentName { get; set; }
        [Required]
        public string StudentPhoneNumber { get; set; }

        public string One { get; set; }

        public string Two { get; set; }

        public string Three { get; set; }

        public string TaskType { get; set; }

        public string Detail { get; set; }
        public string Grade { get; set; }

        public StudyTaskStatus Status { get; set; }

        public DateTimeOffset? CompleteTime { get; set; }
        [Required]
        public AbilityType AbilityType { get; set; }
    }


    public enum AreaList
    {
        [Description("上海")]
        ShangHai = 0,
        [Description("合肥")]
        HeFei = 1,
        [Description("南京")]
        NanJing = 2,
        [Description("苏南")]
        SuNan = 3
    }

    public enum RoleName
    {
        [Description("admin")]
        Admin,
        [Description("admin-area")]
        AdminArea,
        [Description("admin-group")]
        AdminGroup,
        [Description("admin-super")]
        AdminSuper,
        [Description("student")]
        Student,
        [Description("teacher")]
        Teacher,
    }



    public class AdminAppService : WeChatAppServiceBase
    {
        private readonly IAppUserRepository _userRepository;
        private readonly IdentityUserManager _userManager;
        private readonly IRepository<AppTeacher, Guid> _appTeachers;
        private readonly IRepository<AppStudent, Guid> _appStudents;
        private readonly IRepository<AppStudyTask, Guid> _appStudyTasks;

        public AdminAppService(IAppUserRepository userRepository,
            IRepository<AppTeacher, Guid> appteachers,
            IRepository<AppStudent, Guid> appStudents,
            IRepository<AppStudyTask, Guid> appStudyTasks,
            IdentityUserManager userManager)
        {
            this._userRepository = userRepository;
            this._userManager = userManager;
            this._appTeachers = appteachers;
            this._appStudents = appStudents;
            this._appStudyTasks = appStudyTasks;
        }

        [AllowAnonymous]
        public async Task<StudyTaskDto> CreateTask(CreateTaskDto input)
        {
            var now = DateTimeOffset.Now;

            if (input.DeadLine > now.EndOfQuarter())
            {
                throw new UserFriendlyException("截止日期不能超过本季度");
            }

            var teacher = this._userRepository.Where(a => a.PhoneNumber == input.TeacherPhoneNumber && a.Name == input.TeacherName).SingleOrDefault();

            if (teacher == null)
            {
                throw new UserFriendlyException("教师不存在");
            }

            var student = this._userRepository.Where(a => a.PhoneNumber == input.StudentPhoneNumber && a.Name == input.StudentName).SingleOrDefault();

            if (student == null)
            {
                throw new UserFriendlyException("学生不存在");
            }

            var entity = new AppStudyTask()
            {
                Id = GuidGenerator.Create(),
                Year = now.Year,
                Quarter = now.GetQuarter(),
                Title = input.Title,
                DeadLine = input.DeadLine,
                TeacherId = teacher.Id,
                StudentId = student.Id,
                Status = input.Status,
                Content = new StudyTaskContent(),
                CompleteTime = input.CompleteTime,
                AbilityType = input.AbilityType
            };

            ObjectMapper.Map(input, entity.Content);
            await this._appStudyTasks.InsertAsync(entity, true);
            return ObjectMapper.Map<AppStudyTask, StudyTaskDto>(entity);
        }

        [AllowAnonymous]
        public async Task<IdentityUserDto> CreateStudent(CreateStudentDto input)
        {
            var teacher = this._userRepository.Where(a => a.PhoneNumber == input.TeacherPhoneNumber && a.Name == input.TeacherName).SingleOrDefault();

            if (teacher == null)
            {
                throw new UserFriendlyException("教师不存在");
            }
            var student = await CreateUser(input, RoleName.Student);
            var startStudyTime = input.StartStudyTime;

            var Abilitys = new Dictionary<AbilityType, AbilityTypeLevel>();

            foreach (var item in input.Levels)
            {
                Abilitys.Add(item.Key, new AbilityTypeLevel()
                {
                    Level = item.Value,
                    Num = 0,
                    Total = 0,
                    TaskNum = 0
                });
            }

            await _appStudents.InsertAsync(new AppStudent()
            {
                UserId = student.Id,
                TeacherId = teacher.Id,
                Status = StudentStatus.UnGrad,
                StartStudyTime = input.StartStudyTime,
                JoinYear = startStudyTime.Year,
                JoinQuarter = startStudyTime.GetQuarter(),
                AssessScore = null,
                GradTime = null,
                Rating = 0,
                Rank = 0,
                Job = input.Job,
                Abilitys = Abilitys
            }, true);
            return ObjectMapper.Map<IdentityUser, IdentityUserDto>(student);
        }
        [AllowAnonymous]
        public async Task<IdentityUserDto> CreateTeacher(CreateTeacherDto input)
        {
            var user = await CreateUser(input, RoleName.Teacher);

            var now = DateTimeOffset.Now;

            await _appTeachers.InsertAsync(new AppTeacher()
            {
                UserId = user.Id,
                JoinYear = now.Year,
                JoinQuarter = now.GetQuarter(),
                Rating = 0,
                Rank = 0,
                Job = input.Job
            }, true);

            return ObjectMapper.Map<IdentityUser, IdentityUserDto>(user);
        }

        [AllowAnonymous]
        public async Task<IdentityUserDto> CreateAreaAdmin(CreateUserDto input)
        {
            var user = await CreateUser(input, RoleName.AdminArea);

            return ObjectMapper.Map<IdentityUser, IdentityUserDto>(user);
        }

        [AllowAnonymous]
        public async Task<IdentityUserDto> CreateGroupAdmin(CreateUserDto input)
        {
            var user = await CreateUser(input, RoleName.AdminGroup);
            return ObjectMapper.Map<IdentityUser, IdentityUserDto>(user);
        }

        [AllowAnonymous]
        public async Task<IdentityUserDto> CreateSuperAdmin(CreateUserDto input)
        {
            var user = await CreateUser(input, RoleName.AdminSuper);
            return ObjectMapper.Map<IdentityUser, IdentityUserDto>(user);
        }

        private async Task<IdentityUser> CreateUser(CreateUserDto input, RoleName roleName)
        {
            var isExist = this._userRepository.Where(a => a.PhoneNumber == input.PhoneNumber && a.Name == input.Name).Any();
            if (isExist == true)
            {
                throw new UserFriendlyException("用户已经存在");
            }

            var userName = input.PhoneNumber;
            var email = input.PhoneNumber + "@qq.com";

            var user = new IdentityUser(GuidGenerator.Create(), userName, email, CurrentTenant.Id);

            var passWord = ShortId.Generate(true, true, 9) + "w" + "@" + "1";

            (await _userManager.CreateAsync(user, passWord)).CheckErrors();

            await UpdateUserByInput(user, email, input, roleName);

            (await _userManager.UpdateAsync(user)).CheckErrors();


            var appUser = await this._userRepository.GetAsync(user.Id);
            appUser.Area = input.Area.ToString();
            await this._userRepository.UpdateAsync(appUser, true);
            return user;

        }


        private async Task UpdateUserByInput(IdentityUser user, string email, CreateUserDto input, RoleName roleName)
        {
            (await _userManager.SetEmailAsync(user, email)).CheckErrors();
            (await _userManager.SetPhoneNumberAsync(user, input.PhoneNumber)).CheckErrors();
            (await _userManager.SetTwoFactorEnabledAsync(user, false)).CheckErrors();
            (await _userManager.SetLockoutEnabledAsync(user, false)).CheckErrors();

            user.Name = input.Name;

            (await _userManager.SetRolesAsync(user, new string[] {
               EnumUtils.StringValueOf(roleName)
            })).CheckErrors();
        }

        [AllowAnonymous]
        public async Task UpdateGrad(GradStudentDto dto)
        {
            var student = this._userRepository.Where(a => a.PhoneNumber == dto.PhoneNumber && a.Name == dto.Name).SingleOrDefault();
            if (student == null)
            {
                throw new UserFriendlyException("学生不存在");
            }
            var appStudent = this._appStudents.Where(a => a.UserId == student.Id).Single();
            appStudent.Status = dto.Status;

            if (appStudent.Status == StudentStatus.Grad)
            {
                appStudent.GradTime = DateTimeOffset.UtcNow;
            }
            await _appStudents.UpdateAsync(appStudent, true);
        }
    }
}
